import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class UserPreferences {
    private String preferredUnits = "metric";
    private boolean notificationsEnabled = true;
    
    // 位置服务配置
    private boolean autoLocationEnabled = true;
    private long locationCacheTime = 3600000; // 1小时缓存时间（毫秒）
    private boolean askBeforeLocation = false; // 自动获取位置，无需询问用户
    private String lastKnownLocation = ""; // 上次已知位置
    
    // API Configuration
    private String openWeatherMapApiKey = "";
    private String weatherApiComKey = "";
    private String primaryApiSource = "openweather";  // openweather, weatherapi
    private String backupApiSource = "weatherapi";
    private int apiTimeout = 8000;  // milliseconds
    private int maxRetries = 3;
    private boolean enableApiFailover = true;
    private String aggregationStrategy = "PRIMARY_FAILOVER";  // PRIMARY_FAILOVER, PARALLEL_AGGREGATE, BEST_PERFORMANCE, USER_SELECTED
    
    // 新增：预报天数配置
    private int forecastDays = 14; // 默认7天预报
    
    private static final String PREFERENCES_FILE = "resources/userPreferences.properties";
    private static final String ENCRYPTION_KEY = "WeatherApp2024ke"; // 16字节密钥

    public UserPreferences() {
        loadPreferences();
    }

    public String getPreferredUnits() {
        return preferredUnits;
    }

    public void setPreferredUnits(String preferredUnits) {
        this.preferredUnits = preferredUnits;
        savePreferences();
    }

    public boolean isNotificationsEnabled() {
        return notificationsEnabled;
    }

    public void setNotificationsEnabled(boolean enabled) {
        this.notificationsEnabled = enabled;
        savePreferences();
    }
    
    // 位置服务相关的getter和setter
    public boolean isAutoLocationEnabled() {
        return autoLocationEnabled;
    }
    
    public void setAutoLocationEnabled(boolean enabled) {
        this.autoLocationEnabled = enabled;
        savePreferences();
    }
    
    public long getLocationCacheTime() {
        return locationCacheTime;
    }
    
    public void setLocationCacheTime(long cacheTimeMs) {
        this.locationCacheTime = Math.max(300000, cacheTimeMs); // 最少5分钟缓存
        savePreferences();
    }
    
    public boolean isAskBeforeLocation() {
        return askBeforeLocation;
    }
    
    public void setAskBeforeLocation(boolean ask) {
        this.askBeforeLocation = ask;
        savePreferences();
    }
    
    public String getLastKnownLocation() {
        return lastKnownLocation;
    }
    
    public void setLastKnownLocation(String location) {
        this.lastKnownLocation = location != null ? location : "";
        savePreferences();
    }
    
    // API Configuration getters and setters
    public String getOpenWeatherMapApiKey() {
        return openWeatherMapApiKey;
    }
    
    public void setOpenWeatherMapApiKey(String apiKey) {
        this.openWeatherMapApiKey = apiKey != null ? apiKey : "";
        savePreferences();
    }
    
    public String getWeatherApiComKey() {
        return weatherApiComKey;
    }
    
    public void setWeatherApiComKey(String apiKey) {
        this.weatherApiComKey = apiKey != null ? apiKey : "";
        savePreferences();
    }
    
    public String getPrimaryApiSource() {
        return primaryApiSource;
    }
    
    public void setPrimaryApiSource(String source) {
        this.primaryApiSource = source != null ? source : "openweather";
        savePreferences();
    }
    
    public String getBackupApiSource() {
        return backupApiSource;
    }
    
    public void setBackupApiSource(String source) {
        this.backupApiSource = source != null ? source : "weatherapi";
        savePreferences();
    }
    
    public int getApiTimeout() {
        return apiTimeout;
    }
    
    public void setApiTimeout(int timeout) {
        this.apiTimeout = Math.max(1000, Math.min(30000, timeout)); // 1-30 seconds
        savePreferences();
    }
    
    public int getMaxRetries() {
        return maxRetries;
    }
    
    public void setMaxRetries(int retries) {
        this.maxRetries = Math.max(1, Math.min(10, retries)); // 1-10 retries
        savePreferences();
    }
    
    public boolean isEnableApiFailover() {
        return enableApiFailover;
    }
    
    public void setEnableApiFailover(boolean enabled) {
        this.enableApiFailover = enabled;
        savePreferences();
    }
    
    public String getAggregationStrategy() {
        return aggregationStrategy;
    }
    
    public void setAggregationStrategy(String strategy) {
        this.aggregationStrategy = strategy != null ? strategy : "PRIMARY_FAILOVER";
        savePreferences();
    }
    
    // 新增：预报天数配置方法
    public int getForecastDays() {
        return forecastDays;
    }
    
    public void setForecastDays(int days) {
        // 限制天数范围在3-14天之间
        this.forecastDays = Math.max(3, Math.min(14, days));
        savePreferences();
    }
    
    // API key validation
    public boolean hasValidOpenWeatherMapKey() {
        return openWeatherMapApiKey != null && !openWeatherMapApiKey.trim().isEmpty() 
               && openWeatherMapApiKey.length() >= 32; // OpenWeatherMap keys are 32 chars
    }
    
    public boolean hasValidWeatherApiComKey() {
        return weatherApiComKey != null && !weatherApiComKey.trim().isEmpty()
               && weatherApiComKey.length() >= 32; // WeatherAPI.com keys are typically 32+ chars
    }
    
    public boolean hasAnyValidApiKey() {
        return hasValidOpenWeatherMapKey() || hasValidWeatherApiComKey();
    }

    private void savePreferences() {
        Properties properties = new Properties();
        properties.setProperty("preferredUnits", preferredUnits);
        properties.setProperty("notificationsEnabled", String.valueOf(notificationsEnabled));
        
        // 保存位置服务配置
        properties.setProperty("autoLocationEnabled", String.valueOf(autoLocationEnabled));
        properties.setProperty("locationCacheTime", String.valueOf(locationCacheTime));
        properties.setProperty("askBeforeLocation", String.valueOf(askBeforeLocation));
        properties.setProperty("lastKnownLocation", lastKnownLocation);
        
        // Save API configuration (encrypt sensitive data)
        properties.setProperty("openWeatherMapApiKey", encryptString(openWeatherMapApiKey));
        properties.setProperty("weatherApiComKey", encryptString(weatherApiComKey));
        properties.setProperty("primaryApiSource", primaryApiSource);
        properties.setProperty("backupApiSource", backupApiSource);
        properties.setProperty("apiTimeout", String.valueOf(apiTimeout));
        properties.setProperty("maxRetries", String.valueOf(maxRetries));
        properties.setProperty("enableApiFailover", String.valueOf(enableApiFailover));
        properties.setProperty("aggregationStrategy", aggregationStrategy);
        
        // 保存预报天数配置
        properties.setProperty("forecastDays", String.valueOf(forecastDays));

        try (FileOutputStream out = new FileOutputStream(PREFERENCES_FILE)) {
            properties.store(out, "User Preferences and API Configuration");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void loadPreferences() {
        Properties properties = new Properties();

        try (FileInputStream in = new FileInputStream(PREFERENCES_FILE)) {
            properties.load(in);
            preferredUnits = properties.getProperty("preferredUnits", "metric");
            notificationsEnabled = Boolean.parseBoolean(properties.getProperty("notificationsEnabled", "true"));
            
            // 加载位置服务配置
            autoLocationEnabled = Boolean.parseBoolean(properties.getProperty("autoLocationEnabled", "true"));
            locationCacheTime = Long.parseLong(properties.getProperty("locationCacheTime", "3600000"));
            askBeforeLocation = Boolean.parseBoolean(properties.getProperty("askBeforeLocation", "false"));
            lastKnownLocation = properties.getProperty("lastKnownLocation", "");
            
            // Load API configuration (decrypt sensitive data)
            openWeatherMapApiKey = decryptString(properties.getProperty("openWeatherMapApiKey", ""));
            weatherApiComKey = decryptString(properties.getProperty("weatherApiComKey", ""));
            primaryApiSource = properties.getProperty("primaryApiSource", "openweather");
            backupApiSource = properties.getProperty("backupApiSource", "weatherapi");
            apiTimeout = Integer.parseInt(properties.getProperty("apiTimeout", "8000"));
            maxRetries = Integer.parseInt(properties.getProperty("maxRetries", "3"));
            enableApiFailover = Boolean.parseBoolean(properties.getProperty("enableApiFailover", "true"));
            aggregationStrategy = properties.getProperty("aggregationStrategy", "PRIMARY_FAILOVER");
            
            // 加载预报天数配置
            forecastDays = Integer.parseInt(properties.getProperty("forecastDays", "7"));
            // 确保天数在有效范围内
            forecastDays = Math.max(3, Math.min(14, forecastDays));
            
        } catch (IOException e) {
            System.out.println("Preferences file not found. Using default preferences.");
        } catch (NumberFormatException e) {
            System.out.println("Invalid number format in preferences. Using defaults.");
        }
    }
    
    // Simple encryption for API keys (basic security)
    private String encryptString(String plainText) {
        if (plainText == null || plainText.isEmpty()) {
            return "";
        }
        try {
            SecretKeySpec key = new SecretKeySpec(ENCRYPTION_KEY.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] encrypted = cipher.doFinal(plainText.getBytes());
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            System.err.println("Encryption failed: " + e.getMessage());
            return plainText; // Fallback to plain text
        }
    }
    
    private String decryptString(String encryptedText) {
        if (encryptedText == null || encryptedText.isEmpty()) {
            return "";
        }
        try {
            SecretKeySpec key = new SecretKeySpec(ENCRYPTION_KEY.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
            return new String(decrypted);
        } catch (Exception e) {
            System.err.println("Decryption failed: " + e.getMessage());
            return encryptedText; // Fallback to original text
        }
    }
}
